/**
 * author      : dormi330
 * date        : 2018/6/24
 * project     : mybatis
 * description : 领域行为: 创建订单
 */

package org.wzq.learn.domain.order;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.wzq.learn.adaptor.ItemSku;
import org.wzq.learn.adaptor.Member;
import org.wzq.learn.adaptor.MemberAddress;
import org.wzq.learn.utils.CommonUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Service
public class CommandPlaceOrder {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    @Autowired
    private OrderRepository orderRepository;

    /**
     * 新建订单
     *
     * @param tenantCode              租户code
     * @param member                  会员
     * @param address                 地址
     * @param skuAndQtyAndFreightList
     * @throws Exception
     */
    // @Transactional 注解只能应用到 public 可见度的方法上。
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public void placeOrder(
            String tenantCode,
            Member member,
            MemberAddress address,
            List<SkuAndQtyAndFreight> skuAndQtyAndFreightList) throws Exception {

        OrderSummary orderSummary = orderSummary(tenantCode, member, skuAndQtyAndFreightList);
        List<SplitOrderResult> splitOrderResultList = splitOrder(member, address, skuAndQtyAndFreightList, orderSummary);
        saveForNewOrder(orderSummary, splitOrderResultList);

        // TODO 订单创建之后, 如果有支付超时限制, 则启动
    }

    // 事务放在这里控制，方法可见性, private -> public, 没有成功
    // @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    private void saveForNewOrder(OrderSummary orderSummary, List<SplitOrderResult> splitOrderResultList) throws Exception {
        orderRepository.saveOrderSummary(orderSummary);
        for (SplitOrderResult splitOrderResult : splitOrderResultList) {
            orderRepository.saveTradeOrder(splitOrderResult.tradeOrder);
            orderRepository.saveOrderItem(splitOrderResult.orderItem);
            orderRepository.saveOrderDelivery(splitOrderResult.orderDelivery);
        }
    }

    private OrderSummary orderSummary(
            String tenantCode,
            Member member,
            List<SkuAndQtyAndFreight> skuAndQtyAndFreightList) {
        OrderSummary orderSummary = new OrderSummary();
        String id = CommonUtils.uuid();
        orderSummary.setId(id);
        orderSummary.setTenantCode(tenantCode);
        orderSummary.setCreatedBy(member.getId());
        orderSummary.setUpdatedBy(member.getId());
        orderSummary.setMemberId(member.getId());
        orderSummary.setFreightMoney(allFreightMoney(skuAndQtyAndFreightList));
        orderSummary.setPlatformDiscountMoney(platformDiscount());
        orderSummary.setShopDiscountMoney(shopDiscount());
        orderSummary.setItemMoney(allItemMoney(skuAndQtyAndFreightList));

        orderPayMoney(orderSummary);

        return orderSummary;

    }

    private BigDecimal allFreightMoney(List<SkuAndQtyAndFreight> skuAndQtyAndFreightList) {
        BigDecimal totalFreight = new BigDecimal(0.00);

        for (SkuAndQtyAndFreight skuAndQtyAndFreight : skuAndQtyAndFreightList) {
            BigDecimal oneFreight = skuAndQtyAndFreight.getFreight();
            totalFreight = totalFreight.add(oneFreight);
        }
        return totalFreight;
    }


    // 计算平台折扣, 这部分逻辑暂时没有
    private BigDecimal platformDiscount() {
        return new BigDecimal(0.00);
    }

    // 计算店铺折扣, 这部分逻辑暂时没有
    private BigDecimal shopDiscount() {
        return new BigDecimal(0.00);
    }

    // 计算所有 sku的金额 = 求和( sku单价 * 数量 )
    private BigDecimal allItemMoney(List<SkuAndQtyAndFreight> skuAndQtyAndFreightList) {
        BigDecimal allItemMoney = new BigDecimal(0.00);
        for (SkuAndQtyAndFreight skuAndQtyAndFreight : skuAndQtyAndFreightList) {
            BigDecimal itemPrice = skuAndQtyAndFreight.itemSku.getPrice();
            BigDecimal itemMoney = itemPrice.multiply(new BigDecimal(skuAndQtyAndFreight.quanlity));
            allItemMoney = allItemMoney.add(itemMoney);
        }
        allItemMoney.setScale(2, BigDecimal.ROUND_UP);
        return allItemMoney;
    }

    /**
     * 计算订单实付金额, 目前这部分逻辑简单实现
     * = sku金额 + 运费 - 平台折扣 - 店铺折扣
     */
    private void orderPayMoney(OrderSummary orderSummary) {
        BigDecimal payMoney = new BigDecimal(0.00);
        payMoney = payMoney
                .add(orderSummary.getFreightMoney())
                .add(orderSummary.getItemMoney())
                .subtract(orderSummary.getPlatformDiscountMoney())
                .subtract(orderSummary.getShopDiscountMoney());
        orderSummary.setPayMoney(payMoney);
    }

    /**
     * 拆单
     */
    private List<SplitOrderResult> splitOrder(
            Member member,
            MemberAddress address,
            List<SkuAndQtyAndFreight> skuAndQtyAndFreightList,
            OrderSummary orderSummary) {
        List<SplitOrderResult> splitOrderResultList = new ArrayList<>(skuAndQtyAndFreightList.size());

        for (SkuAndQtyAndFreight skuAndQtyAndFreight : skuAndQtyAndFreightList) {
            SplitOrderResult splitOrderResult = new SplitOrderResult();

            TradeOrder tradeOrder = splitOrderOfTradeOrder(orderSummary, skuAndQtyAndFreight, member);
            OrderItem orderItem = splitOrderOfOrderItem(member, orderSummary, skuAndQtyAndFreight, tradeOrder);
            OrderDelivery orderDelivery = splitOrderOfOrderDelivery(member, address, orderSummary, tradeOrder);

            splitOrderResult.tradeOrder = tradeOrder;
            splitOrderResult.orderItem = orderItem;
            splitOrderResult.orderDelivery = orderDelivery;

            splitOrderResultList.add(splitOrderResult);

        }

        return splitOrderResultList;
    }

    // 拆单之 创建TradeOrder
    private TradeOrder splitOrderOfTradeOrder(
            OrderSummary orderSummary,
            SkuAndQtyAndFreight skuAndQtyAndFreight,
            Member member) {
        ItemSku itemSku = skuAndQtyAndFreight.itemSku;
        TradeOrder tradeOrder = new TradeOrder();
        tradeOrder.setId(CommonUtils.uuid());
        tradeOrder.setTenantCode(orderSummary.getTenantCode());
        tradeOrder.setCreatedBy(member.getId());
        tradeOrder.setUpdatedBy(member.getId());

        tradeOrder.setRemark(skuAndQtyAndFreight.remark);
        tradeOrder.setOrderSummaryId(orderSummary.getId());
        tradeOrder.setSellerId(itemSku.getSellerId());
        tradeOrder.setShopId(itemSku.getShopId());
        tradeOrder.setMemberId(member.getId());
        tradeOrder.setStatus(TradeOrder.STATUS_TO_BE_AUDITED);
        tradeOrder.setFreightMoney(skuAndQtyAndFreight.getFreight());
        BigDecimal itemMoney = itemSku.getPrice().multiply(new BigDecimal(skuAndQtyAndFreight.quanlity));
        tradeOrder.setItemMoney(itemMoney);
        tradeOrder.setPayMoney(itemMoney.add(skuAndQtyAndFreight.getFreight()));

        return tradeOrder;
    }

    // 拆单之 创建OrderDelivery
    private OrderDelivery splitOrderOfOrderDelivery(
            Member member,
            MemberAddress address,
            OrderSummary orderSummary,
            TradeOrder tradeOrder) {
        OrderDelivery orderDelivery = new OrderDelivery();
        orderDelivery.setId(CommonUtils.uuid());
        orderDelivery.setTenantCode(orderSummary.getTenantCode());
        orderDelivery.setCreatedBy(member.getId());
        orderDelivery.setUpdatedBy(member.getId());
        orderDelivery.setTradeOrderId(tradeOrder.getId());

        orderDelivery.setProvinceName(address.getProviceName());
        orderDelivery.setCityName(address.getCityName());
        orderDelivery.setDistrictName(address.getDistrictName());
        orderDelivery.setStreetName(address.getStreetName());
        orderDelivery.setPostcode(address.getPostCode());
        orderDelivery.setReceiverName(address.getReceiverName());
        orderDelivery.setRecieverPhone(address.getReceiverPhone());
        orderDelivery.setDetailAddr(address.getDetailAddress());
        orderDelivery.setStatus(OrderDelivery.STATUS_NOT_DELIVERY);
        return orderDelivery;
    }


    // 拆单之 创建OrderItem
    private OrderItem splitOrderOfOrderItem(
            Member member,
            OrderSummary orderSummary,
            SkuAndQtyAndFreight skuAndQtyAndFreight,
            TradeOrder tradeOrder) {
        OrderItem orderItem = new OrderItem();
        orderItem.setId(CommonUtils.uuid());
        orderItem.setTenantCode(orderSummary.getTenantCode());
        orderItem.setCreatedBy(member.getId());
        orderItem.setUpdatedBy(member.getId());

        orderItem.setTradeOrderId(tradeOrder.getId());
        orderItem.setSellerId(skuAndQtyAndFreight.itemSku.getSellerId());
        orderItem.setShopId(skuAndQtyAndFreight.itemSku.getShopId());
        orderItem.setItemId(skuAndQtyAndFreight.itemSku.getItemId());
        orderItem.setBrandId(skuAndQtyAndFreight.itemSku.getBrandId());
        orderItem.setSkuId(skuAndQtyAndFreight.itemSku.getId());
        orderItem.setPriceMoney(skuAndQtyAndFreight.itemSku.getPrice());
        orderItem.setQuantity(skuAndQtyAndFreight.quanlity);
        return orderItem;
    }


    private static class SplitOrderResult {
        TradeOrder tradeOrder;
        OrderItem orderItem;
        OrderDelivery orderDelivery;
    }

}
